"use strict";

var thin = function (selector, context = document) {
  let elements;
  if (typeof selector === "function") {
    return thin.ready(selector);
  } else {
    if (typeof selector === "string") {
      elements = context.querySelectorAll(selector);
    } else if (selector.nodeType) {
      elements = [selector];
    } else if (selector.length) {
      elements = selector;
    }
    //附加扩展接口
    Object.assign(elements, thin.fn);
    return elements;
  }
};

//selector函数容器，由extend填充，并由selector附加到结果集中。
thin.fn = {};

thin.fn.extend = function (ext) {
  Object.assign(thin.fn, ext);
};

// ready queue,
thin.onready = [];

// ?
window.addEventListener("load", (ev) => {
  while (thin.onready.length) {
    thin.onready.shift()();
  }
});

//after queue
thin.afterqueue = [];
thin.after = function (afterrender) {
  thin.afterqueue.push(afterrender);
};
//
thin.ready = function (onready) {
  thin.onready.push(onready);
};

/**
 * 获取cookie值
 * @param {} cname
 * @returns
 */
thin.cookie = function (cname) {
  let name = cname + "=";
  let cookiearray = decodeURIComponent(document.cookie).split(";");
  for (var i = 0; i < cookiearray.length; i++) {
    var c = cookiearray[i];
    while (c.charAt(0) == " ") {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
};

// thin.setCookie = function(cname, cvalue, exdays) {
//     var d = new Date();
//     d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
//     var expires = "expires=" + d.toUTCString();
//     document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
// }

/**
 *
 * @param {*} options
 */
thin.ajax = function (options) {
  options.dataType = options.dataType || "json";
  options.type = options.type || "POST";
  options.contentType = options.contentType || "application/JSON";

  let xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (xhr.readyState != 4) {
    } else if (xhr.status == 200) {
      let d = xhr.responseText;
      console.log({ xhr });
      switch (options.dataType) {
        case "json":
          options.success(JSON.parse(d), xhr.statusText, xhr);
          break;
        default:
          options.success(d, xhr.statusText, xhr);
          break;
      }
    } else if (xhr.status != 200) {
      //console.log({ readyState: xhr.readyState, status: xhr.status, xhr: xhr });
      try {
        xhr.responseJSON = JSON.parse(xhr.responseText);
      } catch (ex) {
        console.log({ ex });
      }
      options.error(xhr, xhr.statusText);
    }
  };

  switch (options.type.toUpperCase()) {
    case "POST":
      //console.log(options);
      xhr.open(options.type, options.url, true);
      xhr.setRequestHeader("Content-Type", options.contentType);
      switch (options.contentType) {
        case "application/x-www-form-urlencoded":
          xhr.send(thin.serialize(options.data));
          break;
        default:
          //console.log(options.contentType);
          xhr.send(JSON.stringify(options.data));
          break;
      }
      break;
    default:
    case "GET":
      //console.log({ pos: "GET", options })
      xhr.open(options.type, options.url, true);
      xhr.send();
      break;
  }
};

thin.post = function (options) {
  options.type = "POST";
  thin.ajax(options);
};

// 将对象序列化成queryString
thin.serialize = function (obj) {
  let arr = [];
  for (let key in obj) {
    arr.push(
      key +
        "=" +
        (typeof obj[key] == "object" ? JSON.stringify(obj[key]) : obj[key])
    );
  }
  return arr.join("&");
};

//
// 这个函数在这里有问题，应该移到render下。
//
thin.append = function (container, content) {
  if (typeof content === "string") {
    //console.log({ container, content })
    let wrapper = document.createElement(container.nodeName);
    let fr = document.createDocumentFragment();
    fr.append(content);
    wrapper.innerHTML = content;
    //console.log({ wrapper, fr, content });
    wrapper.childNodes.forEach((node) => {
      container.appendChild(node.cloneNode(true));
    });
  } else if (content.nodeType) {
    container.appendChild(content);
  } else if (content.length) {
    content.forEach((node) => {
      container.appendChild(node);
    });
  }
};

//
// 这个函数也应该移到render下更合理。
//
/**
 * 归集所有输入数据
 *
 * @param {*} container 从哪个容器下采集。
 * @returns
 */
thin.collectdata = function (container) {
  let data = {};
  if (container)
    thin("input,textarea,select", container).each((e) => {
      console.log({ e });
      if (e.name) {
        data[e.name] = e.value;
      }
    });
  return data;
};

thin.pop = function (p, data) {
  let popmask = document.createElement("popmask");
  popmask.style.zIndex = 1000;
  if (p.onclose) popmask.onclose = p.onclose;
  let modaldialog = document.createElement("popdialog");
  var popcontainer = document.createElement("popbody"); //弹出框-内容
  if (typeof p.width === "number") p.width += "px";
  modaldialog.style.width = p.width || "800px";
  if (typeof p.height === "number") p.height += "px";
  modaldialog.style.height = p.height || "600px";
  //popcontainer.style.overflowY = "scroll";
  popmask.appendChild(modaldialog);

  let header = document.createElement("popheader"); //弹出框-标题

  header.onmousedown = function (ev) {
    var pos_offset = {
      x: modaldialog.offsetLeft - ev.clientX,
      y: modaldialog.offsetTop - ev.clientY,
    };
    document.addEventListener("mouseup", mouseup);
    document.addEventListener("mousemove", mousemove);

    function mousemove(ev) {
      modaldialog.style.left = pos_offset.x + ev.clientX + "px";
      modaldialog.style.top = pos_offset.y + ev.clientY + "px";
    }

    function mouseup(ev) {
      document.removeEventListener("mousemove", mousemove);
      document.removeEventListener("mouseup", mouseup);
    }
  };

  header.innerText = p.header || "untitled";
  let closeicon = document.createElement("closeicon");
  closeicon.innerText = "✕";
  closeicon.onclick = function () {
    thin.popclose(this);
  };
  header.appendChild(closeicon);
  modaldialog.appendChild(header);
  modaldialog.appendChild(popcontainer);
  document.body.appendChild(popmask);

  if (p.render !== undefined) {
    p.render({ container: popcontainer, data: data || p.data });
  } else {
    thin(popcontainer).render(p.template, data || p.data);
  }
};
var poplayer = thin.pop; //兼容V1

thin.popclose = function (context) {
  let container = context;
  while (
    container.parentNode !== undefined &&
    container.tagName !== "POPMASK"
  ) {
    container = container.parentNode;
  }
  if (container) {
    if (container.onclose) container.onclose();
    container.parentNode.removeChild(container);
  }
};

//
// thin(@selector).render(template);
//
thin.rerender = function (context, id) {
  let container = context;

  while (container.thin_query === undefined) {
    container = container.parentNode;
  } //向上遍历查找最近的render锚点。
  container.innerHTML = "";
  console.log({ context, container });
  thin.render_by_template(container, container.thin_template);
};

thin.render_by_template = function (container, template) {
  if (!template) {
    // console.log("no template");
    console.warn("no template");
  } else if (Array.isArray(template)) {
    template.forEach((t) => {
      thin.render_by_template(container, t);
    });
  } else if (typeof template === "string") {
    render_string_template(container, template);
  } else if (typeof template === "function") {
    template({ container: container, data: nearest_data(container) });
  } else {
    // console.log({ template, keys: Object.keys(template) });
    switch (Object.keys(template)[0]) {
      case "gridview":
        gridview_template();
        break;
      case "formview":
        formview_template();
        break;
      case "block":
      case "field":
      case "f1":
      case "f2":
      case "f3":
        formviewitem_template();
        break;
      case "tab":
        tab_template();
        break;
      case "ajax":
        ajax_template();
        break;
      case "foreach":
        foreach_template();
        break;
      case "switch":
        switch_template();
        break;
      case "if":
        if_template();
      default:
        other_template();
        break;
      // console.log({ error: "unknow template", template: template });
    }
  }

  function if_template() {
    if (
      typeof template.if === "function"
        ? template.if({ container: container, data: nearest_data(container) })
        : template.if
    ) {
      thin.render_by_template(container, template.then);
    } else {
      if (template.else) {
        thin.render_by_template(container, template.else);
      }
    }
  }

  /**
   * 标签导航模板
   * @param {*} container
   * @param {*} template
   */
  function tab_template() {
    // console.log({ container, template });
    let currenthashpath = document.location.hash;
    let activeindex = template.tab.default || 0;
    let i = 0;
    // console.log({ currenthashpath });
    let tab = document.createElement("tab");
    for (let item in template.tab.nav) {
      // console.log({ item, t: template.tab.nav[item] });
      let t = template.tab.nav[item];
      let nav = document.createElement("tab-nav");
      nav.innerText = t.t || item;
      if (t.hashpath) {
        // console.log(t);
        let temp = t.click;
        t.click = function (e) {
          // console.log({ pushstate: t.hashpath });
          // if (e)用来判断是实际click，还是主动调用，只有实际click时pushstate
          if (e) history.pushState(null, null, t.hashpath.toLowerCase());
          if (temp) temp(e);
        };
        let reg = RegExp("^".concat(t.hashpath.toLowerCase(), "(?=$|/)"));
        if (reg.test(currenthashpath)) {
          activeindex = i;
          // console.log({ i, match: tab });
        } else {
          // console.log({ reg, currenthashpath });
        }
        i++;
      }

      render_helper(nav, template.tab.nav[item]);
      tab.appendChild(nav);
    }

    container.appendChild(tab);

    let key = Object.keys(template.tab.nav)[activeindex];
    tab.childNodes[activeindex].classList.add("active");

    thin.after(template.tab.nav[key].click); // 将click函数压入afterqueue，当渲染结束时调用。
  }

  function foreach_template(container, template) {
    if (typeof template.foreach === "function") {
      template.t.data = template.foreach;
      thin.render_by_template(container, template.t);
    } else if (typeof template.foreach === "string") {
      template.t.datapath = template.foreach;
      thin.render_by_template(container, template.t);
    } else if (Array.isArray(template.foreach)) {
      template.t.data = template.foreach;
      thin.render_by_template(container, template.t);
    }
  }

  function switch_template() {
    let v = render_content(container, template.switch);
    if (template.case === undefined) {
    } else if (template.case[v] !== undefined) {
      thin.render_by_template(container, template.case[v]);
    } else if (template.case.default !== undefined) {
      thin.render_by_template(container, template.case.default);
    }
  }

  //ajax 模板
  function ajax_template() {
    container.thin_template = template; //锚定模板，以备rerender。
    let loading;
    if (template.loading) {
      loading = document.createElement("loading");
      container.appendChild(loading);
      thin.render_by_template(loading, template.loading);
    }
    container.thin_query = template.query; // 锚定查询参数
    thin.ajax({
      url: template.ajax,
      // data: JSON.stringify(container.thin_query),
      data: container.thin_query,
      dataType: template.dataType || "json",
      contentType: template.contentType || "application/json",
      success: (data) => {
        if (template.debug) {
          console.log({ data });
        }
        if (template.loading) thin(loading).remove();
        container.thin_data = data;
        thin.render_by_template(container, template.success);
        // if (template.pager) render_pager(container, template.pager);
      },
      error: (error, statusText) => {
        console.log({ error, statusText });
        if (template.loading) thin(loading).remove();
        if (template.error) {
          template.error.data = error;
          thin.render_by_template(container, template.error);
        } else {
          let err_template = { e: "error", t: "[[responseText]]", data: error };
          thin.render_by_template(container, err_template);
        }
      },
    });
  }

  //翻页器
  function render_pager(container, pager_template) {
    if (pager_template === true) {
      thin.render_by_template(container, [
        {
          e: "prevpage",
          t: { e: "a", t: "上一页" },
          if: (p) => {
            return p.data.pagenum > 1;
          },
          click: (p) => {
            let query_container = nearest_querycontainer(container);
            query_container.thin_query.pagenum = p.org_data.pagenum - 1;
            thin.rerender(container);
          },
        },
        " [[pagenum]] / [[totalpage]] ",
        {
          e: "prevpage",
          t: { e: "a", t: "下一页" },
          if: (p) => {
            return p.data.pagenum < p.data.totalpage;
          },
          click: (p) => {
            let query_container = nearest_querycontainer(container);
            query_container.thin_query.pagenum = p.org_data.pagenum + 1;
            thin.rerender(container);
          },
        },
      ]);
    } else if (typeof pager_template === "function") {
      pager_template({ container: container, data: nearest_data(container) });
    } else if (typeof pager_template === "object") {
      thin.render_by_template(container, pager_template);
    }
  }

  //查找最近的query容器
  function nearest_querycontainer(context) {
    let query_container = context;
    while (
      query_container !== undefined &&
      query_container.thin_query === undefined
    ) {
      query_container = query_container.parentNode;
    }
    return query_container;
  }

  //表格模板
  function gridview_template() {
    let mode = viewmode(container) || "read";

    let table = document.createElement("table");
    container.appendChild(table);
    let thead = document.createElement("thead");
    table.appendChild(thead);
    let headerrow = document.createElement("tr");
    thead.appendChild(headerrow);
    template.gridview.forEach((col) => {
      let th = document.createElement("th");
      render_helper(th, col);
      th.innerText = col.title;
      headerrow.appendChild(th);
    });

    // 渲染过滤器
    if (
      template.gridview.find((col) => {
        return col.filter !== undefined;
      })
    ) {
      let filterrow = document.createElement("tr");
      thead.appendChild(filterrow);

      template.table.forEach((col) => {
        let td = document.createElement("td");
        filterrow.appendChild(td);
        if (col.filter === undefined) {
        } else if (col.filter.input) {
          thin.render_by_template(td, {
            e: "input",
            name: col.filter.input,
            value: "[[filter/" + col.filter.input + "]]",
          });
        } else if (col.filter.select) {
          if (col.filter.datapath) {
            let options =
              col.filter.emptyforall === true
                ? [""].concat(datarover(td, col.filter.datapath))
                : datarover(td, col.filter.datapath);
            thin.render_by_template(td, {
              e: "select",
              name: col.filter.select,
              value: "[[filter/" + col.filter.select + "]]",
              options: options,
            });
          } else {
            thin.render_by_template(td, {
              e: "select",
              name: col.filter.select,
              value: "[[filter/" + col.filter.select + "]]",
              options: col.filter.options,
            });
          }
        } else thin.render_by_template(td, col.filter);
      });
      //filter事件
      filterrow.addEventListener("change", (ev) => {
        let filter = thin.collectdata(filterrow);
        if (template.onfilter) {
          template.onfilter({ filter: filter });
        } else {
          let querycontainer = nearest_querycontainer(ev.srcElement);
          console.log({ ev: ev, querycontainer: querycontainer });
          querycontainer.thin_query.filter = filter;
          querycontainer.thin_query.pagenum = 1;
          thin.rerender(querycontainer);
        }
      });
    }

    // 渲染表体

    let tbody = document.createElement("tbody");
    table.appendChild(tbody);

    let data = template.data || datarover(container, template.datapath);
    // let d = datarover(container, template.datapath);
    // console.log({ data, datapath: template.datapath, d });
    if (Array.isArray(data)) {
      let rowindex = 0;
      data.forEach((row) => {
        let tr = document.createElement("tr");
        tr.thin_data = row;
        tr.thin_rowindex = rowindex;
        tbody.appendChild(tr);
        let row_template = [];
        if (template.debug) console.log(row);
        template.gridview.forEach((col) => {
          let td = { td: mode === "edit" && col.edit ? col.edit : col.col };
          row_template.push(td);
        });
        thin.render_by_template(tr, row_template);
        rowindex++;
      });
    }

    // 渲染foot
    if (mode === "edit") {
      let tfoot = document.createElement("tfoot");
      table.appendChild(tfoot);
      let tr = document.createElement("tr");
      tfoot.appendChild(tr);
      tr.thin_data = {};
      let row_template = [];
      template.gridview.forEach((col) => {
        row_template.push({ td: col.foot || "" });
      });
      thin.render_by_template(tr, row_template);
    }
  }

  // //查找最近的编辑标记
  // function nearest_editflag(container) {
  //   while (!container.thin_editflag && container.parentNode) {
  //     container = container.parentNode;
  //   }
  //   return container.thin_editflag;
  // }

  function formview_template() {
    let formview = document.createElement("formview");
    container.appendChild(formview);
    formview.thin_viewmode = template.mode || "read";
    let data = template.data || datarover(container, template.datapath);
    if (data) formview.thin_data = data;
    render_helper(formview, template);
    formview.thin_render = function () {
      thin(formview).empty();
      thin.render_by_template(formview, template.formview);
    };
    formview.thin_render();
    // thin.render_by_template(formview, template.formview);
  }

  function formviewitem_template() {
    let field = document.createElement(Object.keys(template)[0]);
    container.appendChild(field);
    // field.style.setProperty("--colspan", template.colspan || 1);

    if (template.title) {
      let label = document.createElement("label");
      label.innerText = template.title;
      field.appendChild(label);
    }

    if (template.edit && viewmode(field) === "edit") {
      thin.render_by_template(field, template.edit);
    } else {
      thin.render_by_template(field, Object.values(template)[0]);
    }
  }

  /**
   *
   * @param {*} element
   * @param {*} template
   *
   */
  function render_helper(element, template) {
    if (template.name !== undefined) {
      element.setAttribute("name", template.name);
    }
    if (template.id !== undefined) {
      element.setAttribute("id", template.id);
    }
    if (template.class !== undefined) {
      element.setAttribute("class", template.class);
    }
    if (template.width) {
      element.style.setProperty(
        "width",
        typeof template.width === "number"
          ? template.width + "px"
          : template.width
      );
    }
    if (template.height) {
      element.style.setProperty(
        "height",
        typeof template.height === "number"
          ? template.height + "px"
          : template.height
      );
    }

    if (template.type) {
      element.setAttribute("type", template.type);
    }
    // if (template.edit !== undefined) {
    //   element.thin_editflag =
    //     typeof template.edit === "function"
    //       ? template.edit({ container: element, data: nearest_data(element) })
    //       : template.edit;
    // }

    //
    // 双向数据绑定
    //
    if (template.bind) {
      let value = datarover(element, template.bind);
      if (
        element.nodeName.toLowerCase() === "input" &&
        element.getAttribute("type") === "checkbox"
      ) {
        console.log({ checkbox: element });
        element.checked = value;
      } else {
        element.value = value !== undefined ? value : "";
      }
      element.addEventListener("change", (ev) => {
        if (
          element.nodeName.toLowerCase() === "input" &&
          element.getAttribute("type") === "checkbox"
        ) {
          // console.log({ value: element.value, checked: element.checked });
          datarover(element, template.bind, element.checked);
        } else {
          datarover(element, template.bind, element.value);
        }
      });
    }

    //
    // 绑定event
    //
    if (template.event) {
      for (let key in template.event) {
        element.addEventListener(
          key,
          (ev) => {
            template.event[key]({
              sender: element,
              org_data: nearest_data(element),
              new_data: thin.collectdata(nearest_datacontainer(element)),
              event: ev,
            });
          },
          false
        );
      }
    }

    //
    // 绑定click事件
    //
    if (template.click) {
      element.addEventListener(
        "click",
        function (e) {
          // 搜集数据
          let datacontainer = nearest_datacontainer(this);
          let new_data = thin.collectdata(datacontainer);
          // console.log({ this: this, datacontainer });

          let para = {
            sender: this,
            org_data: nearest_data(this),
            new_data: new_data,
            rowindex: datacontainer ? datacontainer.thin_rowindex : 0,
            event: e,
          };

          // 构造回调函数
          let formview = nearest_formview(this);

          if (formview) {
            para.editmode = function () {
              formview.thin_viewmode = "edit";
              formview.thin_render();
            };
            para.readmode = function () {
              formview.thin_viewmode = "read";
              formview.thin_render();
            };
          }

          para.rerender = nearest_render(this).thin_render;

          template.click(para);
        },
        false
      );
    }
  }

  /**
   *
   */
  function other_template() {
    // console.log({ container, template });

    let data;
    if (template.data !== undefined) {
      data = template.data;
    } else if (template.datapath !== undefined) {
      data = datarover(container, template.datapath);
    }
    if (Array.isArray(data)) {
      data.forEach((d, i) => {
        render(d, i);
      });
    } else {
      render(data);
    }

    // if (template.when === undefined) {
    // } else if (typeof template.when === "function") {
    //   if (template.when(container, template)) perpare_data();
    // }

    function render(data, rowindex) {
      let element_name = Object.keys(template)[0];
      let element = document.createElement(element_name);
      container.appendChild(element);
      if (data !== undefined) {
        element.thin_data = data;
        if (rowindex) element.thin_rowindex = rowindex;
      }

      if (template.value) {
        thin(element).val(render_content(element, template.value));
      }

      render_helper(element, template);

      // 一些后续处理
      switch (element_name) {
        case "fieldset":
          // fieldset添加title
          if (template.title) {
            let legend = document.createElement("legend");
            legend.innerText = template.title;
            element.appendChild(legend);
          }
          break;

        case "input":
          element.name = template.input;
          break;
        case "select":
          element.name = template.select;
          //
          // select添加选项
          //
          if (template.options) {
            if (typeof template.options === "string") {
              // for (let op in template.options.split(',')) {
              //     element.options.add(new Option(op));
              // }
              let opt = datarover(element, template.options);
              if (Array.isArray(opt)) {
                opt.forEach((op) => {
                  element.options.add(new Option(op));
                });
              }
            } else if (Array.isArray(template.options)) {
              //console.log("isArray!")
              template.options.forEach((op) => {
                element.options.add(new Option(op));
              });
            } else if (typeof template.options === "object") {
              for (let op in template.options) {
                element.options.add(new Option(template.options[op], op));
              }
            }
          }
          break;
        default:
          break;
      }

      //继续渲染子模版；
      thin.render_by_template(element, template[element_name]);
    }
  }

  function render_string_template(container, string_template) {
    thin.append(container, render_content(container, string_template));
  }

  function render_content(container, template) {
    if (typeof template === "function") {
      return template({ container: container, data: nearest_data(container) });
    }
    if (typeof template === "string") {
      const reg = /\[\[[a-zA-Z0-9\-\./_]*\]\]/gi;
      return template.replace(reg, (m) => {
        let path = m.replace("[[", "").replace("]]", "");
        let d = datarover(container, path);
        return d !== undefined ? d : "";
      });
    } else {
      return template;
    }
  }

  function viewmode(node) {
    let formview = nearest_formview(node);
    return formview ? formview.thin_viewmode : "read";
  }

  function nearest_formview(node) {
    // console.log({ node, nodeName: node.nodeName });
    while (node && node.nodeName.toUpperCase() !== "FORMVIEW") {
      // console.log({ nodeName: node.nodeName, parent: node.parentNode });
      node = node.parentNode;
    }
    return node;
  }

  function nearest_render(node) {
    while (node && !node.thin_render) {
      node = node.parentNode;
    }
    return node;
  }

  function nearest_data(node) {
    let datacontainer = nearest_datacontainer(node);
    return datacontainer ? datacontainer.thin_data : undefined;
  }

  function nearest_datacontainer(node) {
    while (node && !node.thin_data) {
      node = node.parentNode;
    }
    return node;
  }

  function datarover(container, datapath, value) {
    if (!datapath) return undefined;
    let patharray = datapath.split("/");
    let datacontainer = nearest_datacontainer(container);

    // console.log({ datacontainer, datapath, patharray });

    if (!datacontainer) return undefined;
    let data = datacontainer.thin_data;
    while (patharray.length > 1) {
      let path = patharray.shift();
      if (path === "..") {
        datacontainer = nearest_datacontainer(datacontainer.parentNode);
        data = datacontainer.thin_data;
        if (!datacontainer) return undefined;
      } else if (path === ".") {
        return data;
      } else {
        if (value !== undefined && data[path] === undefined) data[path] = {};
        data = data[path];
        if (data === undefined) return undefined;
      }
    }
    let path = patharray.shift();
    if (path === ".") {
      if (value !== undefined) data = value;
      return data;
    } else {
      if (value !== undefined) data[path] = value;
      return data[path];
    }
  }
};

//
// 扩展
//
thin.fn.extend({
  each: function (callback) {
    console.log({ each: this });
    this.forEach((node) => {
      callback(node);
    });
  },
  append: function (content) {
    this.forEach((node) => {
      thin.append(node, content);
    });
  },

  val: function (value) {
    if (value !== undefined) {
      this.forEach((node) => {
        node.value = value;
      });
    } else {
      return this[0] !== undefined ? this[0].value : undefined;
    }
  },

  html: function (htmlString) {
    this.forEach((node) => {
      node.innerHTML = htmlString;
    });
    return this[0] !== undefined ? this[0].innerHTML : undefined;
  },

  removeClass: function (classname) {
    this.forEach((node) => {
      node.classList.remove(classname);
    });
    return this;
  },
  addClass: function (classname) {
    this.forEach((node) => {
      node.classList.add(classname);
    });
    return this;
  },

  empty: function () {
    this.forEach((node) => {
      node.innerHTML = "";
    });
    return this;
  },

  remove: function () {
    this.forEach((node) => {
      node.parentNode.removeChild(node);
    });
  },

  attr: function (attribute, value) {
    this.forEach((node) => {
      node.setAttribute(attribute, value);
    });
    return this;
  },

  hide: function () {
    this.forEach((node) => {
      node.thin_org_display = node.style.display;
      node.style.display = "none";
    });
    return this;
  },

  show: function () {
    this.forEach((node) => {
      node.style.display = node.thin_org_display || "";
    });
    return this;
  },

  on: function (event, ...args) {
    let fn = args.pop();
    let childSelector = args.shift();
    this.forEach((node) => {
      if (childSelector) {
        node.addEventListener(event, (ev) => {
          //console.log({ event, ev, node, childSelector });
          let selected = node.querySelectorAll(childSelector);
          selected.forEach((child) => {
            child.thin_on_childSeletor = true;
          }); //加匹配标记
          let target = ev.target;
          while (target) {
            if (target.thin_on_childSeletor) {
              target.thin_temp_fn = fn;
              target.thin_temp_fn(ev);
              delete target.thin_temp_fn;
            }
            target = target.parentNode;
          }
          selected.forEach((child) => {
            delete child.thin_on_childSeletor;
          }); //去除匹配标记
        });
      } else {
        node.addEventListener(event, fn);
      }
    });
    return this;
  },

  //
  //
  //  thin(@selector).render(template,data)
  //
  //
  render: function (template, data) {
    //console.log({ this: this, template: template });
    this.forEach((node) => {
      // thin selector 指向的总是一个节点列表，逐条处理。
      if (data !== undefined) {
        node.thin_data = data;
      }
      node.thin_template = template;
      node.thin_render = function () {
        thin.render_by_template(this, this.thin_template);
      };
      node.thin_render();
    });

    // 执行所有压入afterqueue的操作。
    while (thin.afterqueue.length) {
      thin.afterqueue.shift()();
    }
  },

  //
  // 重新渲染
  //
  rerender: function () {
    this.foreach((node) => {
      if (node.thin_render) node.thin_render();
    });
  },
});

if (typeof $ === "undefined") {
  window.$ = thin;
}

$(function () {
  $(document).on("click", "tab-nav", function (ev) {
    //console.log({ this: this, ev });
    $("tab-nav", this.parentElement).removeClass("active");
    $(this).addClass("active");
  });
});
